package ThreadTest.AccountWithdrawals;
/*
银行账户
 */
public class Account {
    private String id;
    private String name;
    private double balance;

    public Account() {
    }

    public Account(String id, String name, double balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

     public void setName(String name) {
        this.name = name;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public void showBalance(){
        System.out.println(this.getBalance());
    }

    //取款方法
    public void withdraw(double i){
        synchronized(this){
            try {
                Thread.sleep(1000);
                this.setBalance(this.getBalance() - i);
                System.out.println("取款成功");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //存款方法deposit
    public void deposit(double i){
        /*
        synchronized后面小括号中的这个数据是相当关键的，这个数据必须是多线程
        共享的数据，才能达到多线程排队

        这里共享的对象是账户，this就代表当前对象

        在java语言中，任何一个对象都有一把锁，其实把锁就是标记
        100个对象，100把锁，一个对象1把锁

        以下代码执行原理？
            1.假设t1和t2线程并发，开始执行以下代码的时候，肯定有一个先有一个后
            2.假设t1先执行了，遇到synchronized，这个时候自动找后面共享对象的对象锁，找到之后，并占有
            这把锁，然后执行同步代码块中的程序，在程序执行过程中，一直都是占有这把锁的，直到同步代码块代码结束
            这把锁才会释放
            3.假设t1已经占有这把锁此时t2也遇到synchronized关键字，也会去占有后面共享对象的这把锁，结果这把锁被t1占有
            t2只能在同步代码块外面等待t1的结束，直到t1把同步代码块执行结束了，t1会归还这把锁，此时t2终于等到这把锁，然后t2占有
            这把锁之后，进入同步代码块执行程序
            这样就达到了线程排队执行
            注意:这个共享对象一定要选好，这个共享对象一定是你需要排队执行的这些线程对象所共享的
         */
        synchronized(this){
            try {
                Thread.sleep(1000);
                this.setBalance(this.getBalance() + i);
                System.out.println("存款成功");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
